package com.example.demo4.spring.context;

import com.example.demo4.BeanDefinition;
import com.example.demo4.MutablePropertyValues;
import com.example.demo4.PropertyValue;
import com.example.demo4.support.BeanDefinitionRegistry;
import com.example.demo4.xml.XmlBeanDefinitionReader;
import com.example.utils.ToolUtils;
import org.springframework.util.StringUtils;

import java.lang.reflect.Method;
import java.util.Iterator;

/**
 * 具体的实现类 现在这个是获取 classPath下来的xml进行 实例化 bean
 */
public class ClassPathXmlApplicationContext extends AbstractApplicationContext {

    public ClassPathXmlApplicationContext(String configLocation) {
        this.configLocation = configLocation;
        this.beanDefinitionReader = new XmlBeanDefinitionReader();
        this.refresh();

    }

    @Override
    public Object getBean(String name) throws Exception {
        //判断对象容器中 是否包含指定名称的 bean对象,如果包含就返回,否则自行创建
        Object o = singletonObject.get(name);
        if (o != null) {
            return o;
        }
        //自行创建,获取beanDefinition对象
        BeanDefinitionRegistry registry = beanDefinitionReader.getRegistry();
        BeanDefinition beanDefinition = registry.getBeanDefinition(name);


        //通过反射创建对象
        String className = beanDefinition.getClassName();
        Class<?> clazz = Class.forName(className);
        Object beanObj = clazz.newInstance();


        //如果property里面有值的话 也要给这个class set进去
        MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
        Iterator<PropertyValue> iterator = propertyValues.iterator();
        while (iterator.hasNext()) {
            PropertyValue propertyValue = iterator.next();
            //获取name属性值
            String propertyValueName = propertyValue.getName();
            //获取value属性
            String propertyValueValue = propertyValue.getValue();
            //获取ref属性
            String propertyValueRef = propertyValue.getRef();

            if (!StringUtils.isEmpty(propertyValueRef)) {
                Object bean = getBean(propertyValueRef);
                String methodName = ToolUtils.getSettName(propertyValueName);
                Method[] methods = clazz.getMethods();
                for (Method method : methods) {
                    if (methodName.equals(method.getName())) {
                        //执行该set方法
                        method.invoke(beanObj, bean);
                    }
                }


            }
            //如果value不是空的话
            if (!StringUtils.isEmpty(propertyValueValue)) {
                String methodName = ToolUtils.getSettName(propertyValueName);
                //获取method
                Method method = clazz.getMethod(methodName, String.class);
                method.invoke(beanObj, propertyValueValue);
            }

        }

        singletonObject.put(name, beanObj);

        return beanObj;
    }

    @Override
    public <T> T getBean(String name, Class<T> requiredType) throws Exception {
        Object bean = getBean(name);
        if (bean == null) {
            return null;
        }
        return requiredType.cast(bean);
    }
}
